package com.marinesky.mstools.compressor;

import com.marinesky.mstools.common.Constant;
import com.marinesky.mstools.file.FileUtil;
import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
import org.apache.commons.lang.StringUtils;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;

/**
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
    压缩JS文件
*/
public class JsCompressor {


    //option信息

    //在指定位置换行(不换行)
    private static int lineBreak=-1;

    //压缩,是否混淆(默认开启混淆)
    private static boolean nomunge=true;

    //是否去掉冗长的代码
    private static boolean verbose=true;

    //是否保留所有的分号
    private static boolean preserveSemi=false;

    //是否禁用自带的优化措施
    private static boolean disableOptimizations=false;

    //压缩完后文件后缀
    private static String minSuffix=".min";

    //默认文件编码
    private static  String charset="utf-8";


    /**
     * 设置指定位置换行--全局配置(默认不换行)
     * @param lineBreak
     */
    public static void setLineBreak(int lineBreak) {
        JsCompressor.lineBreak = lineBreak;
    }

    /**
     * 是否混淆(命名简化)--全局配置(默认混淆)
     * @param nomunge
     */
    public static void setNomunge(boolean nomunge) {
        JsCompressor.nomunge = nomunge;
    }

    /**
     * 是否保留分号--全局配置(默认保留)
     * @param preserveSemi
     */
    public static void setPreserveSemi(boolean preserveSemi) {
        JsCompressor.preserveSemi = preserveSemi;
    }

    /**
     * 是否禁用自带的优化措施--全局配置(默认不禁用)
     * @param disableOptimizations
     */
    public static void setDisableOptimizations(boolean disableOptimizations) {
        JsCompressor.disableOptimizations = disableOptimizations;
    }

    /**
     * 新生成压缩文件后缀 --全局配置(默认.min)
     * (比如压缩的文件test.js,默认该值为.min,生压缩为test.min.js)
     * @param minSuffix
     */
    public static void setMinSuffix(String minSuffix) {
        JsCompressor.minSuffix = minSuffix;
    }

    public static void setVerbose(boolean verbose) {
        JsCompressor.verbose = verbose;
    }

    public static void setCharset(String charset) {
        JsCompressor.charset = charset;
    }

    /**
     * 压缩JS文件
     * @param in_file_path  -- 输入js文件
     * @param out_dir  -- 输出压缩后js文件目录
     * @return
     */
    public static boolean compressor(String in_file_path,String out_dir) {
        if(StringUtils.isBlank(in_file_path))
        {
            throw new IllegalArgumentException("the in_file_path is Blank");
        }
        File jsInFile=new File(in_file_path);
        return compressor(jsInFile,out_dir);
    }

    /**
     *  压缩JS文件
     * @param in_file -- 输入js文件
     * @param out_dir -- 输出压缩后js文件目录
     * @return
     */
    public static boolean compressor(File in_file,String out_dir) {
        boolean result=false;
        String output_dir=out_dir;
        try{
            if(in_file.exists() && in_file.isFile())
            {
                //获取文件名(不包括后缀)
                String inFileName= FileUtil.getFileName(in_file);
                //获取文件的后缀(不包括点)
                String inFileExtension=FileUtil.getExtension(in_file);
                if(StringUtils.isBlank(output_dir)){
                    output_dir=in_file.getParentFile().getAbsolutePath();
                }
                //输出文件全路径
                String output_file=output_dir+File.separator+inFileName+minSuffix+ Constant.File.FILE_DOT+inFileExtension;

                if(StringUtils.isBlank(charset) || !Charset.isSupported(charset)){
                    throw new IllegalCharsetNameException("the charset is blank or not support!");
                }
                //读取源文件
                Reader in=new InputStreamReader(new FileInputStream(in_file),charset);

                //写压缩后文件
                Writer out=new OutputStreamWriter(new FileOutputStream(output_file),charset);

                JavaScriptCompressor javaScriptCompressor=new JavaScriptCompressor(in, new ErrorReporter() {
                    public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
                        System.out.println("\n[warning] " + line + ':' + lineOffset + ':' + message);
                    }

                    public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
                        System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message);
                    }

                    public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) {
                        error(message, sourceName, line, lineSource, lineOffset);
                        return new EvaluatorException(message);
                    }
                });

                javaScriptCompressor.compress(out,lineBreak,nomunge,verbose,preserveSemi,disableOptimizations);
                out.close();
                in.close();
                result=true;
            }
            else{
                throw new FileNotFoundException("the in_file not found !");
            }
        }catch (Exception e){
            e.printStackTrace();
            result=false;
        }
        return result;
    }

    /**
     *压缩JS文件,默认放在源文件目录
     * @param in_file_path --输入js文件路径
     * @return
     */
    public static boolean compressor(String in_file_path)
    {
       return compressor(in_file_path,null);
    }

    /**
     *压缩JS文件,默认放在源文件目录
     * @param in_file --输入js文件
     * @return
     */
    public static boolean compressor(File in_file)
    {
        return compressor(in_file,null);
    }


    public static void main(String[] args) {
        JsCompressor.setCharset("GBK");
        System.out.println(JsCompressor.compressor("D:\\test1"));
    }
}
